package dq.study.nio.demo;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
import java.util.Iterator;

/**
 * @author dongqun
 * @version 1.0
 * @description ${description}
 * @date 2019/8/29 16:03
 */
public class NioClient extends Thread {
    private CharsetEncoder encoder = Charset.forName("UTF-8").newEncoder();
    private CharsetDecoder decoder = Charset.forName("UTF-8").newDecoder();
    private SocketChannel socket = null;
    private Selector selector = null;
    private SelectionKey clientKey = null;

    public NioClient() {
        try {
            socket = SocketChannel.open();
            socket.configureBlocking(false);
            selector = Selector.open();
            clientKey = socket.register(selector, SelectionKey.OP_CONNECT);
            socket.connect(new InetSocketAddress(12346));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    @Override
    public void run() {
        try {
            while (true) {
                selector.select();
                Iterator<SelectionKey> it = selector.selectedKeys().iterator();
                while (it.hasNext()) {
                    SelectionKey selectionKey = it.next();
                    if (selectionKey.isValid()) {
                        if (selectionKey.isConnectable()) {
                            SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
                            if (socketChannel.isConnectionPending()) {
                                socketChannel.finishConnect();
                            }
                            socketChannel.register(selector, SelectionKey.OP_READ);
                            System.out.println("连接服务端成功");
                        } else if (selectionKey.isReadable()) {
                            SocketChannel channel = (SocketChannel) selectionKey.channel();
                            ByteBuffer buffer = ByteBuffer.allocate(50);
                            try {
                                channel.read(buffer);
                            } catch (IOException e) {
                                System.out.println("与服务器：" + channel.socket().getInetAddress().getHostName() + ":" + channel.socket().getPort() + "的连接已断开");
                                channel.close();
                                continue;
                            }
                            buffer.flip();
                            String msg = decoder.decode(buffer).toString();
                            System.out.println(channel.socket().getInetAddress().getHostName() + ":" + channel.socket().getPort() + "：" + msg);
                            //此处传递中文，会有半个中文问题
//                            CharsetEncoder encoder = Charset.forName("UTF-8").newEncoder();
//                            channel.write(encoder.encode(CharBuffer.wrap("C:  "+msg)));
                        }
                    }
                    it.remove();
                }
            }

        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                selector.close();
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


    public void send(String msg) {
        try {
            SocketChannel client = (SocketChannel) clientKey.channel();
            client.write(encoder.encode(CharBuffer.wrap(msg)));
        } catch (Exception e) {
            System.out.println("发送信息失败");
            e.printStackTrace();
        }
    }

    public void close() {
        try {
            selector.close();
            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
